// ignore: implementation_imports, import_of_legacy_library_into_null_safe
import 'package:build/src/builder/build_step.dart';
import 'package:analyzer/dart/element/element.dart' as ele;
import 'entity.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'json2dart/model_generator.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'package:source_gen/source_gen.dart';

// ignore: import_of_legacy_library_into_null_safe
import 'package:build/build.dart';
import 'dart:io';
import 'tpl/tpl.dart' as tpl;

class EntityGenerator extends GeneratorForAnnotation<GEntity> {
  final separator = Platform.pathSeparator;
  final Map entityMap = Map();
  final Map importMap = Map();

  String buildCode(map) {
    var sb = StringBuffer();
    map.forEach((key, value) {
      sb.writeln("      case '$key': return $key.fromJson(json) as T;");
    });
    return sb.toString();
  }

  String buildImport(map) {
    var sb = StringBuffer();
    map.forEach((key, value) {
      sb.writeln("import '$key';");
    });
    return sb.toString();
  }

  String buildDart(className, jsonRawData, importList, auto) {
    var sb = StringBuffer();
    importList.forEach((v) {
      sb.writeln(v);
    });
    sb.writeln();
    sb.write(tpl.annoTpl(buildJson: jsonRawData, auto: !auto));
    sb.writeln(
        ModelGenerator(className, false).generateDartClasses(jsonRawData).code);
    return sb.toString();
  }

  @override
  generateForAnnotatedElement(
      ele.Element element, ConstantReader annotation, BuildStep buildStep) {
    entityMap[element.name] = null;
    String jsonStr = "";
    bool auto = false;
    var enable = false;
    try {
      enable = annotation.read('enable').boolValue;
    } catch (e) {}
    if (!enable) return null;
    try {
      jsonStr = annotation.read('json').stringValue.trim();
    } catch (e) {}
    try {
      auto = annotation.read('auto').boolValue;
    } catch (e) {}
    if (buildStep.inputId.path.contains('lib/')) {
      var path = buildStep.inputId.path;
      importMap[
              "package:${buildStep.inputId.package}/${path.replaceFirst('lib/', '')}"] =
          null;
    }
    if (auto && jsonStr.length > 0) {
      var importList = [
        "import 'package:xanno/xanno.dart';",
      ];
      var path = buildStep.inputId.path;
      var filePath = '${Directory.current.path}$separator$path';
      File(filePath).writeAsStringSync(
          buildDart(element.name, jsonStr, importList, auto));
    }
    File(
        '${Directory.current.path}${separator}lib${separator}api${separator}entity${separator}entity_factory.entity.dart')
      ..createSync(recursive: true)
      ..writeAsStringSync(tpl.clazzTpl(
          buildCode: buildCode(entityMap),
          buildImport: buildImport(importMap)));
    return null;
  }
}

Builder entityBuilder(BuilderOptions options) =>
    LibraryBuilder(EntityGenerator(), generatedExtension: ".entity.dart");
